package com.stake.web.controller;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.code.linkedinapi.client.LinkedInApiClient;
import com.google.code.linkedinapi.client.LinkedInApiClientException;
import com.google.code.linkedinapi.client.LinkedInApiClientFactory;
import com.google.code.linkedinapi.client.constant.ApplicationConstants;
import com.google.code.linkedinapi.client.constant.LinkedInApiUrls.LinkedInApiUrlBuilder;
import com.google.code.linkedinapi.client.oauth.LinkedInApiConsumer;
import com.google.code.linkedinapi.client.oauth.LinkedInOAuthService;
import com.google.code.linkedinapi.client.oauth.LinkedInOAuthServiceFactory;
import com.google.code.linkedinapi.schema.HttpHeader;
import com.google.code.linkedinapi.schema.Location;
import com.google.code.linkedinapi.schema.Person;
import com.google.code.linkedinapi.schema.impl.LocationImpl;
import com.google.code.linkedinapi.schema.impl.PersonImpl;
import com.stake.entity.Message;
import com.stake.entity.Questions;
import com.stake.entity.UserAnswers;
import com.stake.entity.UserInfo;
import com.stake.model.ActivityTypesEnum;
import com.stake.model.QuestForm;
import com.stake.model.SearchForm;
import com.stake.model.UserInfoView;
import com.stake.util.UserAnswerDescription;

@Controller
@RequestMapping("/profile")
@SessionAttributes("questForm2") 
public class UserProfileController {
	
	public static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(UserProfileController.class);
	
	final String consumerKeyValue = "57vupwf7qm04";
	final String consumerSecretValue = "aHh3om7Zf9q5esFS";
	
	private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
	private ImagesService imagesService = ImagesServiceFactory.getImagesService();
	
	@Autowired
	@Qualifier("persistenceManagerFactory") 
	PersistenceManagerFactory persistenceManagerFactory;
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/n2UserProfile.htm") 
	public ModelAndView showN2UserProfile(){
		Map<String, Object> model = new HashMap<String, Object>();
		
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
		model.put("user", userEntity);
		if(userEntity.getImageBlobKey() != null && !userEntity.getImageBlobKey().equals("undefined")) 
			model.put("imageUrl", imagesService.getServingUrl(new BlobKey(userEntity.getImageBlobKey())));
		else {
			model.put("imageUrl", "http://s.c.lnkd.licdn.com/scds/common/u/img/icon/icon_no_photo_no_border_80x80.png?v=1");
		}
		return new ModelAndView("n2UserProfile", model);
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/questionnaire.htm") 
	public ModelAndView showQuestionnaireForm(@RequestParam String userSetting){
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		
		Map<String, Object> model = new HashMap<String, Object>();
		
		
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(Questions.class);
		List<Questions> questions = new ArrayList<Questions>();
		if(StringUtils.hasText(user.getLinkedInAccessToken())){
			query.setFilter("nonLinkedInUser == nonLinkedInUserParam");
			query.declareParameters("Boolean nonLinkedInUserParam");
			questions = (List<Questions>) query.execute(Boolean.FALSE);
		} else questions = (List<Questions>) query.execute();
		questions = (List<Questions>) manager.detachCopyAll(questions);
		
		Query query2 = manager.newQuery(UserAnswers.class);
		query2.setFilter("userName == userNameParam");
		query2.declareParameters("String userNameParam");
		
		List<UserAnswers> ansList = (List<UserAnswers>) query2.execute(user.getEmail());
		ansList = (List<UserAnswers>) manager.detachCopyAll(ansList); 
		for(Questions question : questions){
			if(!questionExists(ansList, question.getId())){
				UserAnswers answer = new UserAnswers();
				answer.setQuestionId(question.getId());
				answer.setUserName(user.getEmail());
				ansList.add(answer);
			}
		}
		QuestForm form = new QuestForm();
		Collections.sort(ansList, new Comparator<UserAnswers>() {

			@Override
			public int compare(UserAnswers o1, UserAnswers o2) {
				return o1.getQuestionId().compareTo(o2.getQuestionId());
			}
			
		}); 
		form.setAnswers(ansList);
		
		Query query3 = manager.newQuery(UserInfo.class);
		query3.setFilter("email == userNameParam");
		query3.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query3.execute(user.getEmail())).get(0);
		userEntity = manager.detachCopy(userEntity);
		form.setUserInfo(userEntity);
		model.put("questForm2", form);
		model.put("isLinkedInUser", user.getLinkedInAccessToken() != null ? Boolean.TRUE : Boolean.FALSE);
		
		Collections.sort(questions, new Comparator<Questions>() {

			@Override
			public int compare(Questions o1, Questions o2) {
				return o1.getId().compareTo(o2.getId());
			}
			
		});
		
		model.put("questions", questions);
		if(StringUtils.hasText(userSetting)){
			model.put("pageHeading", "Update Your Account Information.");
		} else
			model.put("pageHeading", "Please fill our Questionnaire before you start");
		manager.close();
		if(user.getImageBlobKey() != null){
			model.put("imageAvailable", "true");
		}
		System.out.println(" questions list size : " + questions.size());
		System.out.println(" answers list size : " + ansList.size());
		
		return new ModelAndView("userQuestionnaire", model);
	}
	
	private boolean questionExists(List<UserAnswers> answers, Long questionId){
		for(UserAnswers answer : answers){
			if(answer.getQuestionId().equals(questionId)){
				return true;
			}
		}
		return false;
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/questionnaireSubmit.htm") 
	public @ResponseBody String processQuestionnaireForm(@ModelAttribute("questForm2") QuestForm questForm, HttpServletRequest request){
		System.out.println("question form submitted" );
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		List<UserAnswers> ansList = questForm.getAnswers();
		UserAnswerDescription descUtil = new UserAnswerDescription();
		for(UserAnswers ans : ansList){
			ans.setAnswerDesc(descUtil.getAnswerDescription(ans.getQuestionId(), ans));
			if(ans.getKey() != null){
				UserAnswers oldAns = manager.getObjectById(UserAnswers.class, ans.getKey());
				manager.deletePersistent(oldAns);
			}
			manager.makePersistent(ans);
		}
		
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
		userEntity.setQanswered(Boolean.TRUE);
		user.setQanswered(true);
		
		UserInfo formObj = questForm.getUserInfo();
		userEntity.setFirstName(formObj.getFirstName());
		userEntity.setLastName(formObj.getLastName());
		userEntity.setCompanyName(formObj.getCompanyName());
		userEntity.setCompanyWebsite(formObj.getCompanyWebsite());
		manager.close();
		return "success"; 
	}
	
	@RequestMapping("searchHomePane.htm") 
	public ModelAndView renderSearchPane(){
		
		return new ModelAndView("profileContentPane"); 
	}
	
	@SuppressWarnings("unchecked")
	private void pullUsersByActivity(List<UserInfo> resultList, String[] activities, PersistenceManager manager){
		Query query = manager.newQuery(UserInfo.class);
		StringBuilder sb = new StringBuilder();
		int count = 1;
		for(String activity : activities){
			sb.append("activityTypes.contains(\"" + activity + "\")");
			if(activities.length != count){
				sb.append(" || ");
			}
			count++;
		}
		System.out.println(" query : " + sb.toString());
		query.setFilter(sb.toString());
		resultList.addAll((List<UserInfo>) query.execute()); 
	}
	
	@SuppressWarnings("unchecked")
	public List<UserInfo> filterUsers(SearchForm form, List<UserInfo> list){
		if(form.getActivity() == null && form.getOnline() == null && !StringUtils.hasText(form.getSearchTerm()) ){ 
			return list;
		}
		String term = form.getSearchTerm();
		List<UserInfo> tempList = new ArrayList<UserInfo>();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query2 = manager.newQuery(UserAnswers.class);				
		query2.setFilter("questionId == questionIdParam");
		query2.declareParameters("String questionIdParam");
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("userName == userNameParam");
		query.declareParameters("String userNameParam");
		
		if(form.getActivity() != null) 
			pullUsersByActivity(tempList, form.getActivity(), manager);
		
		if(form.getOnline() != null && form.getOnline().length > 0){
			List<UserAnswers> answers = (List<UserAnswers>) query2.execute(new Long(1014l));
			for(UserAnswers answer : answers){
				if(containsString(answer.getOptionValues(), form.getOnline())){
					extractUserEntity(tempList, query, answer);	
				}
			}
		}
		List<UserInfo> resultList = new ArrayList<UserInfo>();
		if(StringUtils.hasText(term)){
			for(UserInfo userInfo : form.getActivity() == null && form.getOnline() == null ? list : tempList){
				if((userInfo.getFirstName() != null && StringUtils.uncapitalize(userInfo.getFirstName()).contains(StringUtils.uncapitalize(term) )) || (userInfo.getLastName() != null && StringUtils.uncapitalize(userInfo.getLastName()).contains(StringUtils.uncapitalize(term) ))){
					resultList.add(userInfo);
				}
			}
		} else {
			return tempList;
		}
		
		return resultList;
	}
	
	private boolean containsString(List<String> array, String[] checkList){
		for(String el2 : array){
			for(String el1 : checkList){
				if(StringUtils.uncapitalize(el2).contains(StringUtils.uncapitalize(el1))){
					return true;
				}
			}			
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	private void extractUserEntity(List<UserInfo> resultList, Query query, UserAnswers answer) {
		UserInfo userEntity =  ((List<UserInfo>) query.execute(answer.getUserName())).get(0);
		resultList.add(userEntity);
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/searchUserProfile.htm") 
	public @ResponseBody List<UserInfoView> searchPeopleHome(@ModelAttribute("searchForm") SearchForm form){
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("activityTypes.contains(\"PROVIDE_TALK\") || activityTypes.contains(\"PROVIDE_COURSE\") || activityTypes.contains(\"PROVIDE_TRAINING\") " );
		List<UserInfo> userInfoList = (List<UserInfo>) query.execute();
		List<UserInfo> resultUsers = form != null ?  filterUsers(form, userInfoList) : userInfoList ;
		List<UserInfoView> viewList = new ArrayList<UserInfoView>();
		for(UserInfo userInfo: resultUsers ){ 
			Person p = null;
			if(userInfo.getLinkedInAccessToken() != null && !userInfo.getEmail().equals(user.getEmail())){ 
				p = fetchLinkedInData(userInfo);				
			} else if(!userInfo.getEmail().equals(user.getEmail())){
				p = fetchNonLinkedinPerson(manager, userInfo);
			}
			if(p != null){
				UserInfoView viewObj = new UserInfoView();
				viewObj.copyPropsFrom(userInfo);
				viewObj.setPictureUrl(p.getPictureUrl());
				viewObj.setHeadline(p.getHeadline());
				viewObj.setLocation(p.getLocation());
				viewList.add(viewObj);
			}
		} 		
		//manager.close();
		return viewList;
		//return persons;
	}

	@SuppressWarnings("unchecked")
	private Person fetchNonLinkedinPerson(PersistenceManager manager, 
			UserInfo userInfo) {
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		userInfo = ((List<UserInfo>) query.execute(userInfo.getEmail())).get(0);
		Query query2 = manager.newQuery(UserAnswers.class);				
		query2.setFilter("userName == userNameParam && questionId == questionIdParam");
		query2.declareParameters("String userNameParam, String questionIdParam");
		List<UserAnswers> answers = (List<UserAnswers>) query2.execute(userInfo.getEmail(), new Long(1006l));   
		Person nlPerson = new PersonImpl();
		nlPerson.setFirstName(userInfo.getFirstName());
		nlPerson.setLastName(userInfo.getLastName());
		nlPerson.setHeadline(answers.size() == 0 ? "None Specified" : answers.get(0).getAnswer()); 
		answers = (List<UserAnswers>) query2.execute(userInfo.getEmail(), new Long(256l)); 
		Location loc = new LocationImpl();
		StringBuilder locSB = new StringBuilder();
		locSB.append(answers.size() == 0 ? "Unnkown Location" : answers.get(0).getAnswer());
		answers = (List<UserAnswers>) query2.execute(userInfo.getEmail(), new Long(255l)); 
		locSB.append("\n");
		locSB.append(answers.size() == 0 ? "" : answers.get(0).getAnswer());
		answers = (List<UserAnswers>) query2.execute(userInfo.getEmail(), new Long(254l)); 
		locSB.append("\n");
		locSB.append(answers.size() == 0 ? "" : answers.get(0).getAnswer());
		loc.setName(locSB.toString());  
		nlPerson.setLocation(loc);		
		if(StringUtils.hasText(userInfo.getImageBlobKey())){
			BlobKey blobKey = new BlobKey(userInfo.getImageBlobKey());
			nlPerson.setPictureUrl(imagesService.getServingUrl(blobKey)); 
		} else {
			nlPerson.setPictureUrl("http://s.c.lnkd.licdn.com/scds/common/u/img/icon/icon_no_photo_no_border_80x80.png?v=1");
		}
		return nlPerson;
	}

	private Person fetchLinkedInData(UserInfo userInfo) { 
		final LinkedInApiClientFactory factory = LinkedInApiClientFactory.newInstance(consumerKeyValue, consumerSecretValue);
		final LinkedInApiClient client = factory.createLinkedInApiClient(userInfo.getLinkedInAccessToken(), userInfo.getLinkedInTokenSecret());
		LinkedInApiConsumer apiConsumer = new LinkedInApiConsumer(consumerKeyValue, consumerSecretValue);
		System.out.println("Fetching profile for current user.");
		Person profile = client.getProfileForCurrentUser();
		
		
		LinkedInApiUrlBuilder builder2 = new LinkedInApiUrlBuilder("http://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,picture-url,location,email-address)");
		String                apiUrl  = builder2.buildUrl();
		System.out.println("printing email data"); 
		//////////////////////////////////////
		XPathFactory  xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();
		XPathExpression exp = null;
		String pictureUrl = null;
		String headline = null;
		String location = null;
		String email = null;
		try {
			
			
			DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
		    domFactory.setNamespaceAware(true); // never forget this!
		    DocumentBuilder builder = domFactory.newDocumentBuilder();
		    Document doc = builder.parse(callApiMethod(apiUrl, apiConsumer, client));
		    
			
		    location = ((NodeList) xpath.compile("//person/location/name/text()").evaluate(doc, XPathConstants.NODESET)).item(0).getNodeValue();
		    
		    pictureUrl = ((NodeList) xpath.compile("//person/picture-url/text()").evaluate(doc, XPathConstants.NODESET)).item(0).getNodeValue();
		    
		    headline = ((NodeList) xpath.compile("//person/headline/text()").evaluate(doc, XPathConstants.NODESET)).item(0).getNodeValue();
		    
		    email =  ((NodeList) xpath.compile("//person/email-address/text()").evaluate(doc, XPathConstants.NODESET)).item(0).getNodeValue();
			System.out.println("headline : " + headline);
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
		}
		
		
		
		//////////////////////////////////////
		LinkedInApiUrlBuilder builder = new LinkedInApiUrlBuilder("http://api.linkedin.com/v1/people/~/email-address"); 
		String                apiUrl2  = builder.buildUrl();
		System.out.println("printing email data"); 
		String emailAddress = null;
		try {
			exp = xpath.compile("//email-address");
			emailAddress = exp.evaluate(new InputSource(callApiMethod(apiUrl2, apiConsumer, client))); 
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		}
		System.out.println("email address : " + emailAddress); 
		System.out.println("first name : " + profile.getFirstName());
		if(!StringUtils.hasText(pictureUrl)){
			pictureUrl = "http://s.c.lnkd.licdn.com/scds/common/u/img/icon/icon_no_photo_no_border_80x80.png?v=1";
		}
		profile.setPictureUrl(pictureUrl);
		//profile.setMainAddress(profile.getMainAddress()  != null ? profile.getMainAddress()  + ";email:" + email : ";email:" + email); 
		Location loc = new LocationImpl();
		loc.setName(location);
		profile.setLocation(loc);
		return profile;
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/uploadImg.htm") 
	public ModelAndView uploadImage(HttpServletRequest request){
		Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request); 
        List<BlobKey> blobKey = blobs.get("myFile");
        
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
		if(blobKey.size() == 1){
			userEntity.setImageBlobKey(blobKey.get(0).getKeyString());
		} else {
			logger.error("Image upload failed.... ");
		}		
		manager.close();		
		return new ModelAndView();
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/accountInfo.htm") 
	public ModelAndView profileInfo(){
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
		if(!userEntity.getQanswered()){
			//return showQuestionnaireForm(null);
		}
		
		Person nlPerson = new PersonImpl();
		if(user.getLinkedInAccessToken() != null){
			nlPerson = fetchLinkedInData(user);
		} else {
			nlPerson = fetchNonLinkedinPerson(manager, user);
		}
		
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("person", nlPerson);
		model.put("user", userEntity);
		
		Query query3 = manager.newQuery(UserAnswers.class);				
		query3.setFilter("userName == userNameParam");
		query3.declareParameters("String userNameParam");
		List<UserAnswers> allAnswers = (List<UserAnswers>) query3.execute(user.getEmail());
		
		//manager.close();
		model.put("answers", allAnswers);
		for(UserAnswers answer : allAnswers	){
			System.out.println(answer.getAnswerDesc());
		}
		return new ModelAndView("userAccountInfo", model);
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/extUserProfile.htm") 
	public ModelAndView extUserProfileInfo(@RequestParam("userName") String userName){
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		UserInfo userEntity = manager.getObjectById(UserInfo.class, Long.parseLong(userName));
		Query query3 = manager.newQuery(UserAnswers.class);				
		query3.setFilter("userName == userNameParam");
		query3.declareParameters("String userNameParam");
		List<UserAnswers> allAnswers = (List<UserAnswers>) query3.execute(userEntity.getEmail());
		Person person = new PersonImpl();
		if(userEntity.getLinkedInAccessToken() != null){
			person = fetchLinkedInData(userEntity);
		} else {
			person = fetchNonLinkedinPerson(manager, userEntity);
		}
		
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("person", person);
		model.put("user", userEntity);
		model.put("answers", allAnswers);
		return new ModelAndView("extUserProfile", model); 
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/reasonForRegistration.htm")  
	public ModelAndView showReasonForRegistrationPage(){
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0);
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("activities", userEntity.getActivityTypes());
		model.put("allActivities", ActivityTypesEnum.values());
		model.put("userInfo", userEntity);
		manager.detachCopy(userEntity);
		manager.close();
		return new ModelAndView("reasonForRegistration", model); 
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/regReasonFormSubmit.htm") 
	public @ResponseBody String showRegReasonFormSubmit(@ModelAttribute("userInfo") UserInfo userInfo, HttpSession session){
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0); 
		Boolean userForSearchOnly = true;
		for(String activity: userInfo.getActivityTypes()){
			if(activity.contains("PROVIDE")){
				userForSearchOnly = false;
			}
		}
		userEntity.setActivityTypes(userInfo.getActivityTypes());
		userEntity.setFirstName(userInfo.getFirstName());
		userEntity.setLastName(userInfo.getLastName());
		userEntity.setCompanyName(userInfo.getCompanyName());
		userEntity.setCompanyWebsite(userInfo.getCompanyWebsite());
		userEntity.setIsUserOnlyForSearch(userForSearchOnly);
		session.setAttribute("sessionUserName", userEntity.getFirstName() + " " + userEntity.getLastName());
		manager.close();
		if(userForSearchOnly){
			return "registration_complete";
		} else {
			return "show_questionnaire";
		}
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/messages.htm") 
	public ModelAndView showMessages(){
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0); 
		Query query2 = manager.newQuery(Message.class);
		query2.setFilter("toUser == toUserParam");
		query2.declareParameters("String toUserParam");
		List<Message> messages =  (List<Message>) query2.execute(user.getEmail());
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("messages", messages);
		return new ModelAndView("userMessages", model); 
	}
	
	@RequestMapping("/sendMessageForm.htm")  
	public ModelAndView showSendMessageForm(@RequestParam("toUser") String toUser){ 
		Message message = new Message();
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		UserInfo user =  (UserInfo) manager.getObjectById(UserInfo.class, Long.parseLong(toUser)); 
		message.setToUser(user.getEmail());
		manager.close();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("messageForm", message);
		model.put("displayName", user.getFirstName() + " " + user.getLastName());
		return new ModelAndView("sendMessageForm", model); 
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/sendMessage.htm")  
	public ModelAndView sendMessage(@ModelAttribute("messageForm") Message message){  
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		UserInfo user =  (UserInfo)authentication.getPrincipal();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("email == userNameParam");
		query.declareParameters("String userNameParam");
		UserInfo userEntity = ((List<UserInfo>) query.execute(user.getEmail())).get(0); 
		message.setFromUser(userEntity.getEmail());
		message.setDate(new Date());
		manager.makePersistent(message);
		ModelAndView mav = showMessages();
		mav.addObject("resultMessage", "Successfully sent message..");
		return mav;
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/getAllUsers.htm")  
	public @ResponseBody List<UserInfoView> getAllUsers(){
		PersistenceManager manager = persistenceManagerFactory.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		List<UserInfo> entityList = (List<UserInfo>) query.execute();
		List<UserInfoView> viewList = new ArrayList<UserInfoView>();
		for(UserInfo userInfo: entityList ){ 
				UserInfoView viewObj = new UserInfoView();
				viewObj.copyPropsFrom(userInfo);
				viewList.add(viewObj);
		} 		
		manager.close();
		return viewList;
	}
	
	
	/**
    *
    *
    * @param apiUrl
    * @param expected
    * @param httpHeaders
    *
    * @return
    */
   protected InputStream callApiMethod(String apiUrl, LinkedInApiConsumer apiConsumer, LinkedInApiClient client) {
	   List<HttpHeader> httpHeaders = Collections.emptyList(); 
	   Map<String, String> requestHeaders = new HashMap<String, String>(); 
	   /** Field description */
	    final String GZIP_ENCODING = "gzip";
       // by default we compress contents
       requestHeaders.put("Accept-Encoding", "gzip, deflate");
	   int expected = HttpURLConnection.HTTP_OK; 
       try {
           LinkedInOAuthService oAuthService =
               LinkedInOAuthServiceFactory.getInstance().createLinkedInOAuthService(apiConsumer.getConsumerKey(),
                   apiConsumer.getConsumerSecret());
           URL               url     = new URL(apiUrl);
           HttpURLConnection request = (HttpURLConnection) url.openConnection();

           if (ApplicationConstants.CONNECT_TIMEOUT > -1) {
               request.setConnectTimeout(ApplicationConstants.CONNECT_TIMEOUT);
           }

           if (ApplicationConstants.READ_TIMEOUT > -1) {
               request.setReadTimeout(ApplicationConstants.READ_TIMEOUT);
           }

           for (String headerName : requestHeaders.keySet()) {
               request.setRequestProperty(headerName, requestHeaders.get(headerName));
           }
           
           for (HttpHeader header : httpHeaders) {
               request.setRequestProperty(header.getName(), header.getValue());
           }
           
           oAuthService.signRequestWithToken(request, client.getAccessToken());
           request.connect();

           if (request.getResponseCode() != expected) {
              System.out.println("Error Occourred"); 
              return null;
           } else {
               return getWrappedInputStream(request.getInputStream(),
                                            GZIP_ENCODING.equalsIgnoreCase(request.getContentEncoding()));
           }
       } catch (IOException e) {
           throw new LinkedInApiClientException(e);
       }
   }
  
   
   /**
    * Method description
    *
    *
    * @param is
    * @param gzip
    * @return
    * @throws IOException
    */
   protected InputStream getWrappedInputStream(InputStream is, boolean gzip) throws IOException {
       if (gzip) {
           return new BufferedInputStream(new GZIPInputStream(is));
       } else {
           return new BufferedInputStream(is);
       }
   }
}
